/**
 *  @file
 *  @brief   三角形壳单元
 *  @author  yangtianxing
 *  @date    2024.05.16
 *  @version  v1.0
 *  @par Copyright(c):  ShenGong  Simulation corporation
 */

#pragma once
#include "Utility/Algebra/Matrix.h"
#include "Utility/Algebra/Vector3D.h"

#include "DataStructure/Common/Id.h"
#include "DataStructure/Input/Element/CQUAD4Data.h"

#include "../Common/PublicElementExport.h"
#include "SGFem/ElementCalculator/Interface/IElementCalculator.h"
#include "SGFem/PublicElement/Membrane/Tria3SmallDrillMem.h"
#include "SGFem/PublicElement/Plate/MITC3PlateCalculator.h"
#include "SGFem/PublicElement/Plate/TmTPlateCalculator.h"

SG_FEMSOLVER_ELEMENT_NAMESPACE_OPEN

/** @brief 三角形壳单元计算类
 *
 * 单元具有三个节点， 每个节点具有6个自由度。能够负载面内膜变形以及
 * 面外的弯曲和剪切变形。
 *
 * 单元通过膜和板组合完成计算；
 * 考虑到拉弯耦合， 单独的膜和板单元负责相应的应变矩阵计算。数值积分在本单元计算类中完成
 */
class PublicElement_DECLSPEC Tria3ShellCalculator : public SG::FEMSolver::Element::IElementCalculator
{
  public:
    Tria3ShellCalculator ();
    virtual ~Tria3ShellCalculator () = default;

    /** @brief 单元刚度矩阵计算
     * @param [in]  coord        单元局部坐标
     * @param [in]  SecConstant  材料刚度, 必选转换到单元局部坐标系下
     * @param [in]  zOff         壳中面偏置
     * @param [in]  T            单元坐标转换矩阵
     * @param [out] kg           单元全局坐标下刚度矩阵
     */
    void ComputeStiffness (const SG::Algebra::Matrix&                              coord,
                           const SG::FEMSolver::Element::ShellSectionProp1& SecConstant,
                           const SG::DataStructure::Common::Real                   zOff,
                           const SG::Algebra::Matrix&                              T,
                           SG::Algebra::Matrix& _OUT                               kg);

    void ComputeMass (const SG::DataStructure::Common::Real&                  area,
                      const SG::FEMSolver::Element::ShellSectionProp1& secConstant,
                      SG::DataStructure::Common::Real                         zoffs,  // 偏置计算存在问题，暂设为可修改左值
                      _OUT SG::Algebra::Matrixd& coupledM,
                      _OUT SG::Algebra::Matrixd& lumpedM);

    virtual void               Initialize (SG::DataStructure::FEM::ElementTypes type) override;
    virtual void               ComputeElementMatries (const SG::DBManager::DBServiceFactorySP dbServiceFactory) override;
    virtual void               DataRecovery (const SG::DBManager::DBServiceFactorySP             dbServiceFactory,
                                             int                                                 subcaseId, 
                                             SG::DataStructure::Common::Real time,
                                             const std::vector<SG::DataStructure::Common::Real>& globalDisplacement) override;
    virtual void               ComputeStressStiffness (const SG::DBManager::DBServiceFactorySP dbServiceFactory, int staticSubId) override;
    static ElementCalculatorSP Create ()
    {
        return std::make_shared<Tria3ShellCalculator> ();
    }

  private:
    SG::DataStructure::FEM::ElementTypes m_type;
    Tria3SmallDrillMem                   m_mem;
    // MITC3PlateCalculator                 m_plate;
    /**
     * @brief   : 使用TMT只能计算等厚度
     */
    TmTPlateCalculator                    m_plate;
    SG::FEMSolver::Element::Gauss2DTria3P m_integForm;  ///< 积分格式
};

SG_FEMSOLVER_ELEMENT_NAMESPACE_CLOSE